package com.wosiliujing.learning.serialize;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.google.common.base.Preconditions;
import com.wosiliujing.learning.annotations.Sensitive;
import com.wosiliujing.learning.constant.enums.SensitiveTypeEnum;
import com.wosiliujing.learning.util.DesensitizedUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * @author 刘靖
 * @date 2019-09-30 16:50
 */
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {

    /**
     * 脱敏数据类型
     */
    private SensitiveTypeEnum type;
    /**
     *  前置不需要打码的策略
     */
    private Integer prefixNoMaskLen;
    /**
     * 后置不需要打码的长度
     */
    private Integer suffixNoMaskLen;
    /**
     * 打码的标识
     */
    private String maskStr;


    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        Preconditions.checkNotNull(type, "sensitive type can not be null");
        switch (type) {
            case CHINESE_NAME:
                gen.writeString(DesensitizedUtils.chineseName(value));
                break;
            case ID_CARD:
                gen.writeString(DesensitizedUtils.idCardNum(value));
                break;
            case FIXED_PHONE:
                gen.writeString(DesensitizedUtils.fixedPhone(value));
                break;
            case MOBILE_PHONE:
                gen.writeString(DesensitizedUtils.mobilePhone(value));
                break;
            case ADDRESS:
                gen.writeString(DesensitizedUtils.address(value));
                break;
            case EMAIL:
                gen.writeString(DesensitizedUtils.email(value));
                break;
            case BANK_CARD:
                gen.writeString(DesensitizedUtils.bankCard(value));
                break;
            case PASSWORD:
                gen.writeString(DesensitizedUtils.password(value));
                break;
            case KEY:
                gen.writeString(DesensitizedUtils.key(value));
                break;
            case CUSTOMER:
                gen.writeString(DesensitizedUtils.desValue(value,prefixNoMaskLen,suffixNoMaskLen,maskStr));
                break;
            default:
                throw new IllegalArgumentException("unknown sensitive type enum:" + type);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
                                              final BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
                if (sensitive == null) {
                    sensitive = beanProperty.getContextAnnotation(Sensitive.class);
                }
                if (sensitive != null) {
                    return new SensitiveSerialize(sensitive.type(), sensitive.prefixNoMaskLen(), sensitive.suffixNoMaskLen(), sensitive.maskStr());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
